#include "effect_alpha.h"
#include "dirtyrect.h"

namespace animationagent
{

EffectAlpha::EffectAlpha(Uint8 a1, Uint8 a2, Uint32 duration)
{
    fade_starttime_msec = fade_oldtime_msec = SDL_GetTicks();
    fade_endtime_msec = fade_starttime_msec + duration;
    fade_duration_msec = duration;
    alpha_from = a1;
    alpha_to = a2;
    current_alpha = a1;
    alpha_distance = a2 > a1 ? a2 - a1 : a1 - a2;
    undereffecting = true;
    playstyle = ONCE;

    cache_surface = NULL;
}

EffectAlpha::~EffectAlpha()
{
}

int EffectAlpha::Blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect)
{
    int ret = 0;
    Uint32 old_alpha_flags = 0;
    Uint8  old_alpha = 0;

    //save old alpha flag and value
    old_alpha_flags = src->flags & (SDL_SRCALPHA | SDL_RLEACCEL);
    old_alpha = src->format->alpha;
    SDL_SetAlpha(src, SDL_SRCALPHA | SDL_RLEACCEL, current_alpha);
    ret = SDL_BlitSurface(src, srcrect, dst, dstrect);
    //restore old alpha
    SDL_SetAlpha(src, old_alpha_flags, old_alpha);

    return ret;
}

bool EffectAlpha::update()
{
    bool dirty = false;
    if (undereffecting) {
        if (fade_oldtime_msec < fade_endtime_msec) {
            double time;
            fade_oldtime_msec = SDL_GetTicks();
            time = ((float)(fade_oldtime_msec - fade_starttime_msec)) / fade_duration_msec;
            time = time > 1.0 ? 1.0 : time;
            if (alpha_from < alpha_to) {
                current_alpha = (Uint8)(alpha_from + alpha_distance * time);
            } else {
                current_alpha = (Uint8)(alpha_to + alpha_distance * (1 - time));
            }

        } else {
            current_alpha = alpha_to;
            if (playstyle == ONCE) {
                // Do nothing
            } else if (playstyle == LOOP) {
                fade_starttime_msec = fade_oldtime_msec = fade_endtime_msec;
                fade_endtime_msec += fade_duration_msec;
            } else if (playstyle == REVERSAL) {
                fade_starttime_msec = fade_oldtime_msec = fade_endtime_msec;
                fade_endtime_msec += fade_duration_msec;
                Uint8 tmpalpha = alpha_from;
                alpha_from = alpha_to;
                alpha_to = tmpalpha;
            }
        }
        dirty = true;
    }
    return dirty;
}

void EffectAlpha::set_playstyle(enum AnimationStyle style)
{
    playstyle = style;
}

}
